<template>
  <div ref="editor-container" v-loading.lock="initLoading" class="yrt-editor-box" @keydown.f2="submit">
    <yrt-editor-frame :data-options="dataOptions" :edit-type="editType" :title="currentTitle" :label-position="config.labelPosition" :top="currentTop" :width="currentDialogWidth" :visible.sync="isShowDialog" :on-before-close="onBeforeClose" @opened="opened" @on-change-item="onChangeItem">
      <div class="editor-container" @click="editorContainerClick">
        <template v-if="masterFields">
          <el-form ref="editor-form" :inline="config.formInline" :model="formData" :rules="rules" :label-width="config.labelWidth || '100px'" :style="{width:(config.formWidth || 'auto')}" :disabled="currentDisabled" class="editor-master">
            <!--开启tab分组导航-->
            <el-tabs v-if="dataOptions.openTabGroup" v-model="activeTabName">
              <el-tab-pane v-for="(tabGroupName, index) in tabGroupList" :key="index" :label="tabGroupName" :name="tabGroupName">
                <template v-for="(firstField, groupIndex) in getGroupFields(tabGroupName)">
                  <!--数据分组-->
                  <el-row v-if="firstField.type=='grid'" :key="groupIndex" :gutter="firstField.gutter">
                    <el-col v-for="(col, colIndex) in firstField.columns" :key="colIndex" :span="col.span">
                      <yrt-editor-input v-for="(subField, fieldIndex) in col.fields" :key="subField.key + '_' + fieldIndex" :field="subField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur" @on-key-up="(ref, val, event, field, tableData)=>{onKeyup(ref, val, event, field, tableData);}" @on-key-down="(ref, val, event, field, tableData)=>{onKeyDown(ref, val, event, field, tableData);}" @on-row-change="(ref, selectedRow, field, val) => {onRowChange(ref, selectedRow, field, val);}" @on-row-click="(ref, selectedRow, field, val) => {onRowClick(ref, selectedRow, field, val);}" @on-item-click="(ref, val, itemData, field, formData) => {onItemClick(ref, val, itemData, field, formData);}" @on-upload-after="(ref, file, field, formData) => {onUploadAfter(ref, file, field, formData);}">
                        <!-- label插槽 -->
                        <template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
                          <slot :name="'label-' + subField.options.prop" :form-data="formData" :label="subField.label"></slot>
                        </template>
                        <!-- 空白自定义字段插槽 -->
                        <template :slot="'blank-' + subField.options.prop" slot-scope="props">
                          <slot :name="'blank-' + subField.options.prop" :formData="props.formData"></slot>
                        </template>
                        <!-- 上传文件自定义字段插槽 -->
                        <template :slot="'file-' + subField.options.prop" slot-scope="{fileList}">
                          <slot :name="'file-' + subField.options.prop" :file-list="fileList" :formData="formData"></slot>
                        </template>
                      </yrt-editor-input>
                    </el-col>
                  </el-row>

                  <!--分割器-->
                  <div v-else-if="firstField.type=='splitter-group'" :key="groupIndex" class="splitter-title">
                    <div class="title">
                      {{ firstField.label }}
                    </div>
                  </div>

                  <!--编辑框在一行内 / 编辑框独立一行-->
                  <yrt-editor-input v-else ref="editorInput" :key="groupIndex" :field="firstField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur" @on-tree-node-click="(data, node, el, labels, values, field)=>{onTreeNodeClick(data, node, el, labels, values, field)}" @on-upload-after="(ref, file, field, formData) => {onUploadAfter(ref, file, field, formData);}">
                    <!--编辑框在一行内-->
                    <template v-if="firstField.fields">
                      <template v-for="subField in firstField.fields">
                        <!-- label插槽 -->
                        <template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
                          <slot :name="'label-' + subField.options.prop" :form-data="formData" :label="subField.label"></slot>
                        </template>
                        <!-- 空白自定义字段插槽 -->
                        <template :slot="'blank-' + subField.options.prop">
                          <slot :name="'blank-' + subField.options.prop"></slot>
                        </template>
                        <!-- 上传文件自定义字段插槽 -->
                        <template :slot="'file-' + subField.options.prop" slot-scope="{fileList}">
                          <slot :name="'file-' + subField.options.prop" :file-list="fileList" :formData="formData"></slot>
                        </template>
                      </template>
                    </template>
                    <!--编辑框独立一行-->
                    <template v-else>
                      <!-- label插槽 -->
                      <template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(firstField.options.prop)>=0)" :slot="'label-' + firstField.options.prop">
                        <slot :name="'label-' + firstField.options.prop" :form-data="formData" :label="firstField.label"></slot>
                      </template>
                      <!-- 空白自定义字段插槽 -->
                      <template :slot="'blank-' + firstField.options.prop">
                        <slot :name="'blank-' + firstField.options.prop"></slot>
                      </template>
                      <!-- 上传文件自定义字段插槽 -->
                      <template :slot="'file-' + firstField.options.prop" slot-scope="{fileList}">
                        <slot :name="'file-' + firstField.options.prop" :file-list="fileList" :formData="formData"></slot>
                      </template>
                    </template>
                  </yrt-editor-input>
                </template>
              </el-tab-pane>
            </el-tabs>
            <template v-else>
              <template v-for="(firstField, groupIndex) in masterFields">
                <!--数据分组-->
                <el-row v-if="firstField.type=='grid'" :key="groupIndex" :gutter="firstField.gutter">
                  <el-col v-for="(col, colIndex) in firstField.columns" :key="colIndex" :span="col.span">
                    <yrt-editor-input v-for="(subField, index) in col.fields" :key="subField.key + '_' + index" :field="subField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur" @on-key-up="(ref, val, event, field, tableData)=>{onKeyup(ref, val, event, field, tableData);}" @on-key-down="(ref, val, event, field, tableData)=>{onKeyDown(ref, val, event, field, tableData);}" @on-row-change="(ref, selectedRow, field, val) => {onRowChange(ref, selectedRow, field, val);}" @on-row-click="(ref, selectedRow, field, val) => {onRowClick(ref, selectedRow, field, val);}" @on-item-click="(ref, val, itemData, field, formData) => {onItemClick(ref, val, itemData, field, formData);}" @on-tree-node-click="(data, node, el, labels, values, field)=>{onTreeNodeClick(data, node, el, labels, values, field)}" @on-upload-after="(ref, file, field, formData) => {onUploadAfter(ref, file, field, formData);}">
                      <!-- label插槽 -->
                      <template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
                        <slot :name="'label-' + subField.options.prop" :form-data="formData" :label="subField.label"></slot>
                      </template>
                      <!-- 空白自定义字段插槽 -->
                      <template :slot="'blank-' + subField.options.prop" slot-scope="props">
                        <slot :name="'blank-' + subField.options.prop" :formData="props.formData"></slot>
                      </template>
                    </yrt-editor-input>
                  </el-col>
                </el-row>

                <!--分割器-->
                <div v-else-if="firstField.type=='splitter-group'" :key="groupIndex" class="splitter-title">
                  <div class="title">
                    {{ firstField.label }}
                  </div>
                </div>

                <!--编辑框在一行内 / 编辑框独立一行-->
                <yrt-editor-input v-else ref="editorInput" :key="groupIndex" :field="firstField" :form-data="formData" :disabled="currentDisabled" :dropdown-data="dropdownData" :rules="rules" :hide-feilds="hideFeilds" @on-change="(ref, val, field, formData)=>{onChange(ref, val, field, formData);}" @on-focus="(ref, val, event, field)=>{onFocus(ref, val, event, field)}" @on-blur="onBlur" @on-upload-after="(ref, file, field, formData) => {onUploadAfter(ref, file, field, formData);}">
                  <!--编辑框在一行内-->
                  <template v-if="firstField.fields">
                    <template v-for="subField in firstField.fields">
                      <!-- label插槽 -->
                      <template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(subField.options.prop)>=0)" :slot="'label-' + subField.options.prop">
                        <slot :name="'label-' + subField.options.prop" :form-data="formData" :label="subField.label"></slot>
                      </template>
                      <!-- 空白自定义字段插槽 -->
                      <template :slot="'blank-' + subField.options.prop">
                        <slot :name="'blank-' + subField.options.prop"></slot>
                      </template>
                      <!-- 上传文件自定义字段插槽 -->
                      <template :slot="'file-' + subField.options.prop" slot-scope="{fileList}">
                        <slot :name="'file-' + subField.options.prop" :file-list="fileList" :formData="formData"></slot>
                      </template>
                    </template>
                  </template>
                  <!--编辑框独立一行-->
                  <template v-else>
                    <!-- label插槽 -->
                    <template v-if="useLabelSlot===true || (Array.isArray(useLabelSlot) && useLabelSlot.indexOf(firstField.options.prop)>=0)" :slot="'label-' + firstField.options.prop">
                      <slot :name="'label-' + firstField.options.prop" :form-data="formData" :label="firstField.label"></slot>
                    </template>
                    <!-- 空白自定义字段插槽 -->
                    <template :slot="'blank-' + firstField.options.prop">
                      <slot :name="'blank-' + firstField.options.prop"></slot>
                    </template>
                    <!-- 上传文件自定义字段插槽 -->
                    <template :slot="'file-' + firstField.options.prop" slot-scope="{fileList}">
                      <slot :name="'file-' + firstField.options.prop" :file-list="fileList" :formData="formData"></slot>
                    </template>
                  </template>
                </yrt-editor-input>
              </template>
            </template>
          </el-form>
        </template>
        <!--明细数据-->
        <template v-for="(detail, index) in detailFields">
          <div :key="'detail_' + index" class="editor-detail" :class="{'editor-detail-border':!detail.options.isHidden}">
            <div v-if="detail.options.title" class="splitter-title">
              <div class="title">
                {{ detail.options.title }}
              </div>
            </div>
            <template v-if="!detail.options.isHidden">
              <div v-if="detail.buttons.length" class="detail-tool space-between">
                <slot name="detail-tool-slot">
                  <el-form :disabled="currentDetailDisabled(detail)">
                    <template v-for="(button, groupIndex) in detail.buttons">
                      <!--分组按钮-->
                      <el-button-group v-if="button.type=='button-group'" :key="groupIndex" class="tool-group">
                        <template v-for="(btn, btnIndex) in button.buttons">
                          <el-tooltip v-if="authNodes[btn.options.authNode]" :key="btnIndex" :content="btn.label" :open-delay="1000" placement="top">
                            <el-button v-if="authNodes[btn.options.authNode]" v-bind="detailBtnDisabled(btn.options)" size="mini" class="detail-btn" @click.native="()=>onDetailButtonAction(btn.options.authNode, detail, btn)">{{ btn.label }}</el-button>
                          </el-tooltip>
                        </template>
                      </el-button-group>
                      <!--不分组按钮-->
                      <template v-else>
                        <el-tooltip v-if="authNodes[button.options.authNode]" :key="groupIndex" :content="button.label" :open-delay="1000" placement="top">
                          <el-button v-if="authNodes[button.options.authNode]" v-bind="detailBtnDisabled(button.options)" size="mini" class="detail-btn" @click.native="()=>onDetailButtonAction(button.options.authNode, detail, btn)">{{ button.label }}</el-button>
                        </el-tooltip>
                      </template>
                    </template>
                  </el-form>
                </slot>
                <slot name="detail-tool-right-slot">
                </slot>
              </div>
              <el-table :ref="'detail-table-'+detail.subTableView" v-bind="detail.options" :data="getDetailDataList(detail)" :max-height="500" :row-style="({row, rowIndex})=>detailRowStyle(row, rowIndex, detail)" :show-summary="detail.options.showSumField" :summary-method="({ columns, data })=>{return getDetailSummaries(columns, data, detail)}" style="width: 100%" highlight-current-row @row-click="(row)=>{onRowClick(row);}" @selection-change="(val)=>handleSelectionChange(val, detail)" @cell-click="(row, column, cell, event)=>{onDetailCellClick(detail, row, column, cell, event)}" @current-change="(currentRow, oldCurrentRow)=>{onDetailCurrentChange(detail, currentRow, oldCurrentRow)}" @click.native.stop @header-click="(column, event) => {detailHeaderClick(column, event, detail)}" @sort-change="sortChange" @expand-change="(row, expandedRows)=>onExpandChange(row, expandedRows, detail, index)">
                <template>
                  <el-table-column v-if="!detail.options.hiddenCheckCol" width="35px" type="selection" :fixed="!detail.options.checkColScroll?'left':false" class="col-selection">
                  </el-table-column>
                  <el-table-column v-if="!detail.options.hiddenIndexCol" width="40px" :index="(index)=>{return (detail.options.pageIndex-1) * detail.options.pageSize + index+1}" type="index" label="#" :fixed="!detail.options.indexColScroll?'left':false" class="col-index">
                  </el-table-column>
                  <el-table-column v-if="detail.options.showExpandRow" width="35px" type="expand" :fixed="detail.options.expandColFixed?'left':false">
                    <template slot-scope="{row, column, $index}">
                      <slot :row="row" :column="column" :name="'expand-column-slot-'+detail.subTableView">
                      </slot>
                    </template>
                  </el-table-column>
                  <template v-for="(col, fieldIndex) in detail.fields">
                    <!--操作列插槽-->
                    <el-table-column v-if="col.prop=='_action' && !col.hidden" :key="fieldIndex" :sortable="!!col.sortable" :label="col.label" :width="col.width || 'auto'" :header-align="col.headerAlign || 'left'" :align="col.align || 'left'" fixed="right">
                      <template slot-scope="scope">
                        <slot :row="scope.row" :col="col" name="action-column-slot">
                          <el-button v-for="(btn, btnIndex) in col.action" :key="btnIndex" type="text" size="mini" @click="()=>onRowActionClick(btn, col, scope.row)">{{ btn.label }}</el-button>
                        </slot>
                      </template>
                    </el-table-column>

                    <!--通用列插槽-->
                    <yrt-detail-column :key="fieldIndex" :col="col" :data-options="dataOptions" :dropdown-data="dropdownData" :disabled="currentDisabled" :show-fields="showFields" :current-row="detail.currentRow" :load-data-before="loadDataBefore" @on-detail-change="(ref, val, row, field)=>onDetailChange(ref, val, row, field, getDetailDataList(detail))">
                      <template v-if="useDetailSlot===true || (Array.isArray(useDetailSlot) && useDetailSlot.indexOf(col.prop)>=0)" slot="column-slot" slot-scope="{ row, column, _index }">
                        <slot :detail="detail" :row="row" :col="col" :index="_index" name="detail-column-slot"></slot>
                      </template>
                    </yrt-detail-column>

                  </template>
                </template>
              </el-table>
              <div v-if="!detail.options.isHidden" class="pagination-container">
                <el-pagination :disabled="detailPageDisabled" :current-page="detail.options.pageIndex" :page-sizes="[5, 10, 15, 20, 50, 100, 200, 300, 500, 1000]" :page-size="detail.options.pageSize" :total="formData[detail.subTableView].total" layout="total, sizes, prev, pager, next, jumper" @size-change="(val)=>handleSizeChange(val, detail)" @current-change="(val)=>handleCurrentChange(val, detail)">
                </el-pagination>
              </div>
            </template>
            <div v-else class="button-box">
              <slot name="detail-tool-slot">
                <el-form :disabled="currentDetailDisabled(detail)">
                  <template v-for="(button, groupIndex) in detail.buttons">
                    <!--分组按钮-->
                    <el-button-group v-if="button.type=='button-group'" :key="groupIndex" class="tool-group">
                      <template v-for="(btn, btnIndex) in button.buttons">
                        <el-tooltip v-if="authNodes[btn.options.authNode]" :key="btnIndex" :content="btn.label" :open-delay="1000" placement="top">
                          <el-button v-if="authNodes[btn.options.authNode]" v-bind="detailBtnDisabled(btn.options)" size="mini" class="detail-btn" @click.native="()=>onDetailButtonAction(btn.options.authNode, detail, btn)">{{ btn.label }}</el-button>
                        </el-tooltip>
                      </template>
                    </el-button-group>
                    <!--不分组按钮-->
                    <template v-else>
                      <el-tooltip v-if="authNodes[button.options.authNode]" :key="groupIndex" :content="button.label" :open-delay="1000" placement="top">
                        <el-button v-if="authNodes[button.options.authNode]" v-bind="detailBtnDisabled(button.options)" size="mini" class="detail-btn" @click.native="()=>onDetailButtonAction(button.options.authNode, detail, btn)">{{ button.label }}</el-button>
                      </el-tooltip>
                    </template>
                  </template>
                </el-form>
              </slot>
            </div>
            <!--明细自定义插槽-->
            <slot :name="'detail-' + index" :detail="detail" :detail-data-list="getDetailDataList(detail)"></slot>
          </div>
        </template>
      </div>

      <div v-if="action!=='search'" slot="footer" class="dialog-footer">
        <div class="left">
          <!--自定义按钮-->
          <template v-for="(item, index) in buttonList">
            <el-button v-if="authNodes[item.authName]" :key="index" :disabled="btnReadOnly[item.authName]" :type="item.type" :icon="item.icon" @click.native="onButtonAction(item.authName)">{{ item.label }}</el-button>
          </template>

          <slot :form-data="formData" :details="detailFields" name="footer-button-region"></slot>
        </div>
        <div class="right">
          <span style="color:white;cursor:pointer;margin-right:10px;" @click="showMainFieldsDialog=true">字段</span>
          <span style="color:white;cursor:pointer;" @click="$message.info('主键ID：' + dataOptions.idValue)">ID值</span>
          <el-button-group>
            <el-button icon="el-icon-yrt-guanbi1" @click="cancel">取 消</el-button>
            <el-button :loading="saveLoading" :disabled="currentDisabled || btnReadOnly['save'] || !authNodes.save" type="primary" icon="el-icon-yrt-baocun2" @click="submit(false)">{{ config.saveButtonText }}(F2)</el-button>
            <el-button v-if="editType!=='inner'" :loading="saveLoading" :disabled="currentDisabled || btnReadOnly['save'] || !authNodes.save" type="primary" icon="el-icon-yrt-baocun2" @click="submit(true)">保存并关闭</el-button>
          </el-button-group>
        </div>
      </div>
    </yrt-editor-frame>

    <!-- 批量导入对话框 -->
    <import-dialog ref="import-dialog" v-dialogDrag :options="batchImport.options" :visible.sync="batchImport.visible" :import-data="importData"></import-dialog>

    <!-- 批量导出对话框 -->
    <export-dialog ref="export-dialog" v-dialogDrag :options="batchExport.options" :visible.sync="batchExport.visible" :export-data="exportData">
    </export-dialog>

    <!--显示主表字段属性-->
    <table-info-dialog :visible.sync="showMainFieldsDialog" :data-options="dataOptions" :fields="mainFields">
    </table-info-dialog>

    <!--显示明细字段属性-->
    <table-info-dialog :visible.sync="tableAttr.showAttrDialog" :data-options="tableAttr.dataOptions" :fields="tableAttr.fields">
    </table-info-dialog>
  </div>
</template>

<script>
import yrtEditorInput from "./yrtEditorInput";
import yrtDetailColumn from "./yrtDetailColumn";
import ImportDialog from "./components/import-dialog";
import ExportDialog from "./components/export-dialog";
import yrtEditorFrame from "./components/yrt-editor-frame";
import TableInfoDialog from "./components/table-info-dialog";
import Vue from "vue";
import eventBus from "@/utils/eventBus";
Vue.config.keyCodes.f2 = 113;
Vue.config.keyCodes.f3 = 114;

export default {
  name: "yrt-editor",
  components: {
    yrtEditorInput,
    yrtDetailColumn,
    ImportDialog,
    ExportDialog,
    yrtEditorFrame,
    TableInfoDialog
  },
  props: {
    // 编辑类型：inner、dialog
    editType: {
      type: String,
      default: "dialog"
    },
    // 对话框宽度
    dialogWidth: {
      type: [Number, String],
      default: null
    },
    // 编辑类型：add、edit
    action: {
      type: String,
      default: "add",
      validator: function (value) {
        // 接收值为：add、edit
        return ["add", "edit", "search"].indexOf(value) !== -1;
      }
    },
    // 校验规则
    rules: {
      type: Object,
      default: () => {
        return null;
      }
    },
    // 主表字段信息
    fields: {
      type: Array,
      default: () => {}
    },
    // 数据参数
    dataOptions: {
      type: Object,
      default: () => {}
    },
    // 配置参数
    config: {
      type: Object,
      default: () => {
        return {
          top: "10vh",
          title: "对话框标题",
          // 是否显示添加实验室小组对话框
          visible: false,
          // 是否禁用
          disabled: false,
          // 编辑时KeyId
          id: 0,
          // 保存按钮文本
          saveButtonText: "保存",
          // 行内表单模式
          formInline: true
        };
      }
    },
    // 明细按钮单击事件
    detailButtonClick: {
      type: Function,
      required: false,
      default: null
    },
    // 编辑按钮点击事件
    editButtonClick: {
      type: Function,
      required: false,
      default: null
    },
    // 关联列表ref名
    dataListRef: {
      type: String,
      default: "data-list"
    },
    // 权限集合
    authNodes: {
      type: Object,
      required: true,
      default: () => {
        return {};
      }
    },
    // 按钮列表
    buttonList: {
      type: Array,
      required: false,
      default: () => {
        return [
          {
            label: "审核",
            authName: "auditing",
            icon: "el-icon-yrt-gouxuan1",
            type: "success"
          },
          {
            label: "复制",
            authName: "copy",
            icon: "el-icon-yrt-fuzhi",
            type: "success"
          },
          {
            label: "终止",
            authName: "stop",
            icon: "el-icon-yrt-zhongzhiicon",
            type: "success"
          },
          {
            label: "开启",
            authName: "open",
            icon: "el-icon-yrt-kaiqi",
            type: "success"
          }
        ];
      }
    },
    // 表单默认值，新建时用
    defaultValue: {
      type: Object,
      required: false,
      default: () => {
        return {};
      }
    },
    // 按钮是否可用
    btnReadOnly: {
      type: Object,
      required: false,
      default: () => {
        return {
          save: false,
          auditing: false,
          add: false,
          delete: false,
          stop: false,
          open: false
        };
      }
    },
    // 关闭前钩子函数，return true可关闭对话框
    beforeClose: {
      type: Function,
      required: false,
      default: () => {
        return true;
      }
    },
    // 明细字段使用插槽，值为true=所有列都使用插槽；值为数组，数组中存在的字段使用插槽
    useDetailSlot: {
      type: [Boolean, Array],
      default: false
    },
    // 主表使用标签插槽，值为true=所有字段都使用插槽；值为数组，数组中存在的字段使用插槽
    useLabelSlot: {
      type: [Boolean, Array],
      default: false
    },
    // 修改数据事件
    onSaveBefore: {
      type: Function,
      default: () => {}
    },
    // 终止前事件
    onStopBefore: {
      type: Function,
      default: () => {
        return true;
      }
    },
    // 删除前事件
    onDetailDeleteBefore: {
      type: Function,
      default: () => {
        return true;
      }
    },
    // 数据处理方法
    doDataParser: {
      type: Function,
      required: false,
      default: null
    },
    // 审核成功后，不可编辑处理方法
    auditDisabled: {
      type: Function,
      required: false,
      default: null
    },
    // 控制显示字段,true=显示所有字段，Array=只显示数组内的字段
    showFields: {
      type: [Boolean, Array],
      default: true
    },
    // 自定义查询条件
    filteredValue: {
      type: Array,
      default: null
    },
    // 额外下拉框ID
    dropdownIds: {
      type: Array,
      default: () => {
        return [];
      }
    },
    // 隐藏字段
    hideFeilds: {
      type: Array,
      default: () => {
        return [];
      }
    },
    // 明细按钮是否禁用
    detailButtonCustom: {
      type: Boolean,
      default: false
    },
    // 输入选择框加载前方法
    loadDataBefore: {
      type: Function,
      default: () => {
        return () => {};
      }
    }
  },
  data () {
    return {
      saveLoading: false, // 保存loading
      initLoading: false, // 加载数据初始化loading
      formData: {}, // 表单数据集合，明细数据集合:{subTableView:{total:10,rows:[{}], footer:[{}]}}
      dropdownData: {}, // 下拉框数据集合
      dropdownLoaded: false, // 下拉框已加载
      // 模块tree prop参数配置
      treeProps: {
        label: "label",
        children: "children",
        value: "value",
        isLeaf: function (data, node) {
          return data.hasChild !== 1;
        }
      },
      // TREE选择器右侧图标
      treeSuffixIcon: "el-icon-yrt-xiangxiajiantou1",
      // 显示批量导入对话框参数
      batchImport: {
        visible: false,
        label: "批量导入",
        options: {
          url: "/api/common/upload",
          importInfo_Id: 0,
          vueData_Id: 0,
          fId: 0 // 主表主键值
        }
      },
      // 显示批量导出对话框参数
      batchExport: {
        visible: false,
        label: "批量导出",
        options: {
          exportInfo_Id: 0,
          vueData_Id: 0
        }
      },
      // 明细分页器禁用
      detailPageDisabled: true,
      // 显示字段属性对话框
      tableAttr: {
        showAttrDialog: false,
        dataOptions: {},
        fields: []
      },
      // 当前选中tab
      activeTabName: null,
      // 保存后关闭
      isSavedCloseDialog: true,
      // 显示字段属性对话框
      showMainFieldsDialog: false
    };
  },
  computed: {
    // 当前宽度
    currentDialogWidth: function () {
      if (this.dialogWidth) {
        const width = Number.isInteger(this.dialogWidth) ? this.dialogWidth + "px" : this.dialogWidth;
        return width;
      } else {
        const width = Number.isInteger(this.config.width) ? this.config.width + "px" : this.config.width;
        return width;
      }
    },
    // 主表字段
    masterFields: function () {
      if (this.fields) {
        return this.fields.filter(item => item.type !== "detail-grid");
      } else {
        return [];
      }
    },
    // 明细字段
    detailFields: function () {
      if (this.fields) {
        var details = this.fields.filter(item => item.type === "detail-grid");

        // 初始化明细数据结构
        details.forEach(detail => {
          const subTableView = detail.subTableView;
          if (!this.formData[subTableView]) {
            this.$set(this.formData, subTableView, {
              total: 0,
              rows: [],
              footer: []
            });
          }
        });

        return details;
      } else {
        return [];
      }
    },
    // 主表字段属性，字段弹出框使用
    mainFields: function () {
      if (this.fields) {
        let newFields = [];
        const _f = this.fields.filter(item => ["grid", "detail-grid", "splitter-group", "inline-group"].indexOf(item.type) < 0);
        newFields = newFields.concat(
          _f.map(m => {
            return {
              prop: m.options.prop,
              label: m.label,
              dataType: m.options.dataType,
              width: m.options.width,
              type: m.options.type,
              isExpandField: m.options.isExpandField
            };
          })
        );
        this.fields
          .filter(item => ["grid", "inline-group"].indexOf(item.type) >= 0)
          .forEach(item => {
            if (item.type === "grid") {
              for (const col of item.columns) {
                newFields = newFields.concat(
                  col.fields.map(m => {
                    return {
                      prop: m.options.prop,
                      label: m.label,
                      dataType: m.options.dataType,
                      width: m.options.width,
                      type: m.type,
                      isExpandField: m.options.isExpandField
                    };
                  })
                );
              }
            } else if (item.type === "inline-group") {
              newFields = newFields.concat(
                item.fields.map(m => {
                  return {
                    prop: m.options.prop,
                    label: m.label,
                    dataType: m.options.dataType,
                    width: m.options.width,
                    type: m.type,
                    isExpandField: m.options.isExpandField
                  };
                })
              );
            }
          });
        return newFields;
      } else {
        return [];
      }
    },
    // 标题名称
    currentTitle: function () {
      if (!this.config.hiddenTitle) {
        if (this.config.title) {
          let subTitle = "编辑";
          if (this.action === "add") {
            subTitle = "新建";
          } else if (this.action === "edit") {
            subTitle = "编辑";
          } else if (this.action === "search") {
            subTitle = "查询条件";
          }
          return this.config.title + " - " + subTitle;
        } else {
          return "编辑数据";
        }
      } else {
        return "";
      }
    },
    // 是否显示dialog
    isShowDialog: {
      get: function () {
        return this.config.visible;
      },
      set: function (newValue) {
        this.$emit("update:visible", newValue); // 双向绑定prop.visible，通知父级组件变量值同步更新
      }
    },
    // 当前编辑动作：add/edit
    currentAction: {
      get: function () {
        return this.action;
      },
      set: function (newValue) {
        this.$emit("update:action", newValue); // 双向绑定prop.action，通知父级组件变量值同步更新
      }
    },
    // 当前diaolog top
    currentTop: {
      get: function () {
        return this.config.top;
      },
      set: function (newValue) {
        this.$emit("update:config.top", newValue); // 双向绑定，通知父级组件变量值同步更新
      }
    },
    // 是否禁用
    currentDisabled: {
      get: function () {
        return this.config.disabled || false;
      },
      set: function (newValue) {
        this.$emit("update:config.disabled", newValue); // 双向绑定，通知父级组件变量值同步更新
      }
    },
    // 明细按钮是否禁用
    currentDetailDisabled: {
      get: function () {
        return detail => {
          if (this.detailButtonCustom) {
            return false;
          } else {
            return this.config.disabled || false;
          }
        };
      }
    },
    // 明细按钮是否禁用
    detailBtnDisabled: {
      get: function () {
        return options => {
          options.disabled = !!this.btnReadOnly[options.authNode];
          return options;
        };
      }
    },
    // 判断明细是否提供自定义插槽
    // detailExistSlotContent: {
    //   get: function() {
    //     return !!this.$slots["detail-column-slot"];
    //   }
    // },
    // tab分组
    tabGroupList: function () {
      if (this.fields) {
        let groupList = this.masterFields.reduce(
          (all, next) => (all.some(item => item.tabGroupName === next.tabGroupName) ? all : [...all, next]),
          []
        );
        // 初始化明细数据结构
        groupList = groupList.map(item => {
          return item.tabGroupName || "[未分组]";
        });

        return groupList;
      } else {
        return [];
      }
    }
  },
  watch: {
    formData: {
      handler (formData) {
        // 审核成功，将不可编辑
        if (typeof this.auditDisabled === "function") {
          this.auditDisabled(formData, this.config);
        } else {
          if (formData.auditing === 2) {
            this.$set(this.config, "disabled", true);
          } else {
            this.$set(this.config, "disabled", false);
          }
        }
      },
      deep: true
    },
    masterFields: {
      handler (val) {},
      deep: true
    },
    tabGroupList: {
      handler (groupList) {
        // 设置第一项默认选中项
        if (groupList.length) {
          this.activeTabName = groupList[0];
        }
      },
      deep: true
    }
  },
  mounted () {
    this.bindEvent();
  },
  methods: {
    // 事件处理
    bindEvent () {
      // 重置事件定义
      eventBus.$on("loadDropDown", ({ authNode, btnOpts, btn }) => {
        if (this.dataOptions.router === this.$route.path) {
          // 重新加载下拉框和列表数据
          this.reLoadDropDown();
        }
      });
    },
    // 扩展按钮事件
    onButtonAction (authNode) {
      var result;
      if (this.editButtonClick) {
        result = this.editButtonClick(authNode, this.formData);
      }
      if (result !== undefined) {
        return;
      }
      switch (authNode) {
        case "auditing":
          // 审核
          this.auditing();
          break;
        case "copy":
          // 复制
          this.copy();
          break;
        case "stop":
          // 终止
          this.stop();
          break;
        case "open":
          // 终止
          this.open();
          break;
      }
    },
    // 明细按钮单击事件
    onDetailButtonAction (authNode, detail, btnOpts) {
      var result;
      if (this.detailButtonClick) {
        result = this.detailButtonClick(authNode, detail, btnOpts);
      }
      if (result !== undefined) {
        return;
      }
      const row = {};
      switch (authNode) {
        case "detailAdd":
          // 批量添加
          detail.fields.forEach(field => {
            this.$set(row, field.prop, null);
          });
          this.addDetailDataRow([row], detail.subTableView);
          break;
        case "detailDelete":
          // 批量删除
          this.detailDelete(detail.options.detailSelections, detail, btnOpts);
          break;
        case "detailImport":
          // 批量导入
          this.importDialog(btnOpts);
          break;
        case "detailExport":
          // 批量导出
          this.exportDialog(btnOpts);
          break;
      }
    },
    // 获取默认值
    getDefaultValue (fields) {
      fields.forEach(item => {
        if (["detail-grid"].indexOf(item.type) >= 0) {
          return true;
        }
        if (["grid"].indexOf(item.type) >= 0) {
          item.columns.forEach(col => {
            this.getDefaultValue(col.fields);
          });
        } else if (["inline-group"].indexOf(item.type) >= 0) {
          this.getDefaultValue(item.fields);
        } else {
          if (!item.options.defaultValue && item.options.defaultValue !== 0) {
            return;
          }

          if (["radio"].indexOf(item.type) >= 0) {
            let v = item.options.defaultValue;
            if (item.options.dataType === "float") {
              v = parseFloat(item.options.defaultValue);
            }
            this.$set(this.formData, item.options.prop, v);
          } else if (item.options.prop === "consignorName") {
            // 货主设置默认值
            const v = item.options.defaultValue;
            if (v) {
              const vList = v.split(",");
              this.$set(this.formData, "consignor_Id", vList[0]);
              this.$set(this.formData, "consignorCode", vList[1]);
              this.$set(this.formData, "consignorName", vList[2]);
            }
          } else if (item.options.prop === "providerShortName") {
            // 货主设置默认值
            const v = item.options.defaultValue;
            if (v) {
              const vList = v.split(",");
              this.$set(this.formData, "provider_Id", vList[0]);
              this.$set(this.formData, "providerCode", vList[1]);
              this.$set(this.formData, "providerShortName", vList[2]);
            }
          } else if (item.options.prop === "storageName") {
            // 仓库设置默认值
            const v = item.options.defaultValue;
            if (v) {
              const vList = v.split(",");
              this.$set(this.formData, "storage_Id", vList[0]);
              this.$set(this.formData, "storageName", vList[1]);
            }
          } else if (["byte", "int32"].indexOf(item.options.dataType) >= 0) {
            this.$set(this.formData, item.options.prop, parseInt(item.options.defaultValue));
          } else if (["number", "float"].indexOf(item.options.dataType) >= 0) {
            this.$set(this.formData, item.options.prop, parseFloat(item.options.defaultValue));
          } else if (["date", "datetime"].indexOf(item.options.dataType) >= 0) {
            var defaultValue = item.options.defaultValue;
            if (defaultValue === "{currentDate}") {
              const format = item.options.format || "YYYY-MM-DD HH:mm:ss";
              defaultValue = this.common.formatDate(new Date(), format);
            }
            this.$set(this.formData, item.options.prop, defaultValue);
          } else {
            defaultValue = item.options.defaultValue;
            // 当前默认用户
            if (defaultValue === "{currentUserTrueName}") {
              const userTrueName = this.common.getUserInfo().userTrueName;
              this.$set(this.formData, "userTrueName", userTrueName);
              const user_Id = this.common.getUserInfo().user_Id;
              this.$set(this.formData, "user_Id", user_Id);
            } else if (defaultValue === "{currentDeptName}") {
              const deptName = this.common.getUserInfo().deptName;
              this.$set(this.formData, "deptName", deptName);
              const dept_Id = this.common.getUserInfo().dept_Id;
              this.$set(this.formData, "dept_Id", dept_Id);
            } else {
              this.$set(this.formData, item.options.prop, item.options.defaultValue);
            }
          }
        }
      });
    },
    // 获得主表字段信息
    getFieldInfo (fieldName) {
      // 字段信息
      var fieldInfo = null;
      var _getDropDownId = function (array) {
        array.forEach(item => {
          if (item.type === "grid") {
            item.columns.forEach(colItem => {
              _getDropDownId(colItem.fields);
            });
          } else if (item.type === "inline-group") {
            _getDropDownId(item.fields);
          } else if (item.type === "detail-grid") {
            _getDropDownId(item.fields);
          } else {
            if (item.options && item.options.prop === fieldName) {
              fieldInfo = item;
            }
          }
        });
      };
      _getDropDownId(this.fields);

      return fieldInfo;
    },
    // 获得主明细字段信息
    getDetailFieldInfo (fieldName) {
      const _fields = this.detailFields[0].fields;
      return _fields.find(item => item.prop === fieldName);
    },
    // 加载下拉框数据
    loadDropDown (refresh, isLoading) {
      if (isLoading === undefined) isLoading = true;

      if (this.dropdownLoaded && !refresh) return; // 已加载下拉框不在重复加载
      // 获得下拉框ID
      var ddIDs = this.dropdownIds || [];
      var _getDropDownId = function (array) {
        array.forEach(item => {
          if (item.type === "grid") {
            item.columns.forEach(colItem => {
              _getDropDownId(colItem.fields);
            });
          } else if (item.type === "inline-group") {
            _getDropDownId(item.fields);
          } else if (item.type === "detail-grid") {
            _getDropDownId(item.fields);
          } else {
            if (item.options && item.options.dropdown_Id) {
              ddIDs.push(item.options.dropdown_Id);
            } else if (item.dropdown_Id) {
              // 明细下拉框ID
              ddIDs.push(item.dropdown_Id);
            }
          }
        });
      };
      _getDropDownId(this.fields);
      if (!ddIDs.length) return;

      this.initLoading = true;
      var url = "/api/common/loadDropDown";
      var params = Object.assign({}, this.dataOptions, {
        where: ddIDs.join(","),
        data: JSON.stringify(this.formData)
      });
      this.common.ajax(
        url,
        params,
        res => {
          res = this.common.objectToCase(res);
          if (res.result) {
            this.dropdownLoaded = true; // 记录已加载下拉框数据
            Object.keys(res.data).forEach((key, index) => {
              this.$set(this.dropdownData, key, res.data[key]);
            });
          } else {
            this.$message({
              showClose: true,
              duration: 6000,
              message: res.msg,
              type: "error"
            });
          }
          this.initLoading = false;
          // 下拉框加载完毕后事件
          this.$emit("on-load-dropdown-after", this.formData);
        },
        true
      );
    },
    /**
     * 重新加载下拉框数据
     * @isLoading 是否显示loading
     */
    reLoadDropDown (isLoading) {
      this.dropdownLoaded = false;
      this.loadDropDown(true, isLoading);
    },
    // 外部设置下拉框值，例如联动
    setDropdownData (dropdown_Id, data) {
      this.$set(this.dropdownData, "dropdown" + dropdown_Id, data);
    },
    // 获得下拉框值
    getDropdownData (dropdown_Id) {
      return this.dropdownData["dropdown" + dropdown_Id];
    },
    // 根据字段获得下拉框值
    getDropdownDataByProp (prop) {
      const fields = this.detailFields[0].fields;
      const propInfo = fields.find(item => item.prop === prop);
      let datas = [];
      if (propInfo) {
        const dropdown_Id = propInfo.options.dropdown_Id;
        const ddList = this.getDropdownData(dropdown_Id);
        if (ddList) {
          datas = ddList;
        } else {
          const options = propInfo.options.options;
          datas = options;
        }
      }
      return datas;
    },
    // 允许外部调用新建数据
    addData () {
      this.isShowDialog = true;
      this.currentAction = "add";
      this.detailPageDisabled = true;
      var top = this.common.getDialogTop();
      this.config.top = top;
      Object.keys(this.formData).forEach(key => {
        if (Array.isArray(this.formData[key])) {
          this.formData[key] = [];
        } else if (this.common.isObject(this.formData[key])) {
          this.formData[key] = {
            total: 0,
            rows: [],
            footer: []
          };
        } else {
          this.formData[key] = null;
        }
      });
      this.loadDropDown();
      this.getDefaultValue(this.fields);
      // 新建设置默认值
      Object.keys(this.defaultValue).forEach((key, index) => {
        if (["value", "label"].indexOf(key) < 0) {
          this.$set(this.formData, key, this.defaultValue[key]);
        }
      });

      // 编辑器中的默认值
      const editorDefaultValue = this.dataOptions.editorDefaultValue;
      if (editorDefaultValue) {
        Object.keys(editorDefaultValue).forEach((key, index) => {
          this.$set(this.formData, key, editorDefaultValue[key]);
        });
      }

      // 可编辑
      this.currentDisabled = false;
      this.$nextTick(() => {
        // 清除验证
        this.$refs["editor-form"].clearValidate();

        // 添加加载后事件
        this.$emit("on-add-load-after", this.formData);
      });

      return this.formData;
    },
    // 允许外部调用编辑数据
    editData (id = 0, rowData, isInit) {
      if (isInit) {
        // 将明细分页码初始化为1
        this.detailFields.forEach(item => {
          item.options.pageIndex = 1;
        });
      }

      // 编辑加载前事件
      this.$emit("on-edit-load-before", rowData);
      this.isShowDialog = true;
      this.currentAction = "edit";
      this.detailPageDisabled = false;
      this.initLoading = true;
      var top = this.common.getDialogTop();
      this.currentTop = top;

      this.getDefaultValue(this.fields);
      this.loadDropDown();
      this.dataOptions.idValue = id;

      var url = "/api/common/loadEditData";
      var params = Object.assign({}, this.dataOptions);
      // 明细参数处理
      params.detailList = this.detailFields.map(item => {
        const newItem = Object.assign(
          {
            tableName: item.subTableView
          },
          item.options
        );
        if (item.folder) {
          newItem.folder = item.folder;
        }
        if (item.options.showSumField) {
          newItem.sumColumnNames = item.fields
            .filter(f => f.isSum)
            .map(m => m.prop)
            .join(",");
        }
        return newItem;
      });

      this.common.ajax(
        url,
        params,
        res => {
          this.common.showMsg(res);
          if (res.result) {
            this.showData(res.data, params);
          }
          this.initLoading = false;
        },
        true
      );
    },
    // 显示数据
    showData (dataInfo, params, showType = "load") {
      // 原始数据加工处理
      if (typeof this.doDataParser === "function") {
        this.doDataParser(dataInfo);
      }

      if (!dataInfo) {
        this.$message.error("没有加载到数据！");
        this.initLoading = false;
        return;
      }
      const tranData = this.translate(dataInfo);
      if (showType === "save") {
        params.detailTableList.forEach(item => {
          tranData[item.detailViewName] = this.formData[item.detailViewName];
        });
      }
      this.formData = tranData;
      // 设置主键ID
      this.dataOptions.idValue = this.formData[this.dataOptions.idField];
      // 明细数据处理
      this.detailFields.forEach(detail => {
        const subTableView = detail.subTableView;
        // 新数据集合
        const newDetailInfo = dataInfo[subTableView];
        this.translateDetails(detail, newDetailInfo.rows);
        if (showType === "save") {
          const newRows = newDetailInfo.rows;
          // 修改前数据集合
          const oldRows = this.formData[subTableView].rows;
          oldRows.forEach((oldRow, index) => {
            const newRow = newRows[index];
            if (newRow) {
              Object.keys(oldRow).forEach(key => {
                oldRow[key] = newRow[key];
              });
            }
          });
        } else {
          this.$set(this.formData, subTableView, newDetailInfo);
        }
      });
      this.$nextTick(() => {
        // 清除验证
        window.setTimeout(() => {
          this.$refs["editor-form"].clearValidate();
        }, 50);
        // 编辑加载后事件
        this.$emit("on-edit-load-after", this.formData);
      });
    },
    // 获得明细数据集
    getDetailDataList (detailInfo) {
      if (typeof detailInfo === "string") {
        detailInfo = {
          subTableView: detailInfo
        };
      }
      if (detailInfo.subTableView) {
        const dataList = this.formData[detailInfo.subTableView];
        if (dataList && dataList.rows.length) {
          return dataList.rows;
        } else {
          return [];
        }
      } else {
        return [];
      }
    },
    // 刷新数据
    reload () {
      this.editData(this.dataOptions.idValue);
    },
    // 主表数据转换
    translate (dataObj) {
      // 转换函数
      const _translate = fields => {
        fields.forEach(field => {
          var prop = field.options.prop;
          const v = dataObj[prop];
          if (
            field.type === "cascader" ||
            (field.type === "select" && field.options.multiple) ||
            (field.type === "date" && field.options.type === "dates")
          ) {
            if (Array.isArray(v)) {
              return v;
            } else if (v) {
              dataObj[prop] = v.split("/");
              if (["int", "int32", "byte", "decimal"].indexOf(field.options.dataType) >= 0) {
                dataObj[prop].forEach((p, index) => {
                  dataObj[prop][index] = Number(p);
                });
              }
              // 主键ID处理为数组
              const keyProp = field.options.keyProp;
              if (keyProp) {
                const keyValues = dataObj[keyProp];
                if (keyValues) {
                  if (!Array.isArray(keyValues)) {
                    if (typeof keyValues === "number") {
                      dataObj[keyProp] = [keyValues];
                    } else {
                      dataObj[keyProp] = keyValues.split("/");
                    }
                  }
                  dataObj[keyProp].forEach((item, index) => {
                    dataObj[keyProp][index] = Number(item);
                  });
                } else {
                  dataObj[keyProp] = [];
                }
              }
            } else {
              dataObj[prop] = [];
            }
          } else if (field.type === "checkbox") {
            if (Array.isArray(v)) {
              return v;
            } else if (v) {
              dataObj[prop] = v.split("/");
            } else {
              dataObj[prop] = [];
            }
          } else if (field.dataType === "decimal" || ["float", "decimal"].indexOf(field.options && field.options.dataType) >= 0) {
            let scale = 2;
            if (field.formatter) {
              const arr = field.formatter.split(".");
              scale = arr[1].length;
            } else if (field.options.formatter) {
              const arr = field.options.formatter.split(".");
              scale = arr[1].length;
            }
            dataObj[prop] = Math.Round(v, scale); // 保留两位小数
          } else if (field.dataType === "date" || (field.options && field.options.dataType === "date")) {
            if (v) {
              let formatter = "yyyy-MM-dd";
              if (field.formatter) formatter = field.formatter;
              dataObj[prop] = this.common.formatDate(v, formatter);
            }
          } else if (field.dataType === "datetime" || (field.options && field.options.dataType === "datetime")) {
            if (v) {
              let formatter = "yyyy-MM-dd HH:mm:ss";
              if (field.formatter) formatter = field.formatter;
              dataObj[prop] = this.common.formatDate(v, formatter);
            }
          }
        });
      };

      // 循环转换
      this.fields.forEach(item => {
        if (["detail-grid"].indexOf(item.type) >= 0) {
          return true;
        }

        if (["grid"].indexOf(item.type) >= 0) {
          item.columns.forEach(col => {
            _translate(col.fields);
          });
        } else if (["inline-group"].indexOf(item.type) >= 0) {
          _translate(item.fields);
        }
      });
      _translate(this.fields);

      return dataObj;
    },
    // 明细表数据转换
    translateDetails (detail, detailRows) {
      try {
        for (const row of detailRows) {
          detail.fields.forEach(field => {
            var prop = field.prop;
            let v = row[prop];
            if (v === undefined) v = "";
            if (field.dataType === "date") {
              if (v) {
                let formatter = "yyyy-MM-dd";
                if (field.formatter) formatter = field.formatter;
                v = this.common.formatDate(v, formatter);
                this.$set(row, prop, v);
              }
            } else if (field.dataType === "datetime") {
              if (v) {
                let formatter = "yyyy-MM-dd HH:mm:ss";
                if (field.formatter) formatter = field.formatter;
                v = this.common.formatDate(v, formatter);
                this.$set(row, prop, v);
              }
            } else if (field.dataType === "decimal") {
              let scale = 2;
              if (field.formatter === "%") {
                scale = 2;
              } else if (field.formatter) {
                const arr = field.formatter.split(".");
                scale = arr.length <= 1 ? 0 : arr[1].length;
              }
              v = Math.Round(v, scale); // 保留两位小数
              this.$set(row, prop, v);
            } else {
              // 将数据转为触发数据
              this.$set(row, prop, v);
            }
          });
        }
      } catch (error) {
        console.log(error);
      }
    },
    // 翻译下拉框值
    translateText (prop, val, dropdown_Id) {
      var ddList = this.dropdownData["dropdown" + dropdown_Id];
      if (!ddList) return val;
      var item = ddList.find((item, index, arr) => {
        return item.value === val;
      });
      if (!item) return val;
      return item.label;
    },

    // 修改主表字段值
    changeValue (prop, value) {
      this.$set(this.formData, prop, value);
      if (this.$refs["editor-form"]) {
        this.$refs["editor-form"].validate();
      }
    },

    // 关闭对话框
    cancel () {
      this.$emit("update:visible", !this.config.visible); // 双向绑定prop.visible，通知父级组件变量值同步更新
    },
    // 提交数据
    async submit (isClose, callback) {
      // 禁止保存
      if (this.currentDisabled || this.btnReadOnly["save"] || !this.authNodes.save) {
        this.$message.error("当前单子禁止保存");
        return;
      }
      this.isSavedCloseDialog = !!isClose;
      return new Promise((resolve, reject) => {
        this.$refs["editor-form"].validate(valid => {
          let result = false;
          if (valid) {
            result = this.saveCheck(callback);
          } else {
            this.$message.error("表单验证不通过，请正确填写表单！");
            result = false;
          }
          resolve(result); // 返回 状态给qiankun
        });
      });
    },
    // 保存数据
    saveCheck (callback) {
      // 保存前事件
      const reValue = this.onSaveBefore(this.formData, callback);
      if (reValue === false) {
        this.saveLoading = false;
        return false;
      }
      this.save(callback);
      return true;
    },
    // 保存数据
    save (callback) {
      this.setExtendFields();
      this.saveLoading = true;
      const data = {};
      // 数据转换
      Object.keys(this.formData).forEach(key => {
        let val = this.formData[key];
        if (val === "") val = null;
        if (Array.isArray(val)) {
          val = val.join("/");
          data[key] = val;
        } else if (val !== null && typeof val === "object" && val.rows) {
          data[key] = val.rows.filter(row => {
            return row.__ischange__;
          });
          for (const row of data[key]) {
            // 明细数据处理
            Object.keys(row).forEach(subKey => {
              let val = row[subKey];
              if (val === "") val = null;
              if (Array.isArray(val)) {
                val = val.join("/");
                row[subKey] = val;
              }
            });
          }
        } else {
          data[key] = val;
        }
      });
      // 明细表
      const detailTableList = this.detailFields.map(item => {
        const newItem = Object.assign(
          {
            subTableView: item.subTableView
          },
          item.options
        );
        if (item.folder) {
          newItem.folder = item.folder;
        }
        if (item.options.showSumField) {
          newItem.sumColumnNames = item.options.sumColumnNames;
        }
        return newItem;
      });

      const url = "/api/common/saveEditData";
      const params = Object.assign({}, this.dataOptions, {
        data: JSON.stringify(data),
        noDataSign: true, // 数据不参与签名
        detailTableList: detailTableList
      });
      this.common.ajax(
        url,
        params,
        res => {
          this.common.showMsg(res);
          if (res.result) {
            if (res.data) {
              this.showData(res.data, params, "save");
              var ref = this.findRef(this.dataListRef);
              if (ref) {
                ref.loadData();
              }
              // 保存后事件
              this.$emit("on-save-after", this.formData);
              if (typeof callback === "function") {
                setTimeout(() => {
                  callback();
                }, 800);
              } else {
                if (this.isSavedCloseDialog) {
                  this.isShowDialog = false;
                }
              }
            } else {
              this.$message.warning("保存数据返回数据失败！");
              // this.isShowDialog = false;
            }
          }
          this.saveLoading = false;
        },
        true
      );
    },
    // 明细删除数据
    detailDelete (selectedRows, detail, btnOpts) {
      // 禁止删除
      if (this.currentDetailDisabled(detail) || !!this.btnReadOnly[btnOpts.options.authNode]) {
        this.$message.error("当前单子明细禁止删除");
        return;
      }
      if (!selectedRows.length) {
        this.$message.error("至少选择一项！");
        return;
      }
      // 终止前事件
      const reValue = this.onDetailDeleteBefore(selectedRows, detail);
      if (!reValue) return;
      this.$confirm("此操作将永久删除选中的数据, 是否继续?", "删除操作", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          _delete();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除"
          });
        });

      const _delete = () => {
        var deletedIDs = selectedRows
          .map((item, index, Array) => {
            return item[detail.options.idField] || "0";
          })
          .filter(item => {
            return item !== "0";
          })
          .join(",");
        if (!deletedIDs) {
          // 没有任何已经保存要删除的数据
          selectedRows.forEach((item, index, Array) => {
            // 删除明细
            var _detailRow = this.formData[detail.subTableView].rows;
            _detailRow.splice(
              _detailRow.findIndex(_row => _row === item),
              1
            );
          });
          this.$message.success("数据删除成功");
          return;
        }

        var url = "/api/common/deleteData";
        this.initLoading = true;
        var params = Object.assign({}, this.dataOptions, {
          projectName: this.dataOptions.projectName,
          tableName: detail.subTableView,
          tableView: detail.subTableView,
          deletedIDs: deletedIDs,
          idField: detail.options.idField
        });
        this.common.ajax(
          url,
          params,
          res => {
            this.common.showMsg(res);
            if (res.result) {
              selectedRows.forEach((item, index, Array) => {
                // 删除明细
                var _detailRow = this.formData[detail.subTableView].rows;
                _detailRow.splice(
                  _detailRow.findIndex(_row => _row === item),
                  1
                );
              });
              // 明细删除后事件
              this.$emit("on-detail-delete-after", selectedRows, detail);
              setTimeout(() => {
                this.isSavedCloseDialog = false; // 自动保存后不关闭窗口
                this.save(); // 保存数据，防止数据修改
              }, 50);
              // 明细改变事件
              this.$emit("on-detail-change", null, null, selectedRows, null);
            }
            this.initLoading = false;
          },
          true
        );
      };
    },
    // 添加明细数据
    addDetailDataRow: function (rows, subTableView) {
      if (!Array.isArray(rows)) {
        this.$message.error("添加明细数据必须为数组");
        return;
      }
      if (!subTableView && this.detailFields.length) {
        // 默认为第一个明细表名称
        subTableView = this.detailFields[0].subTableView;
      }
      if (subTableView) {
        rows.forEach(row => {
          row.__ischange__ = true; // 新增
          row[this.dataOptions.idField] = 0; // 新增时外键ID为0
          this.$set(this.formData[subTableView].rows, this.formData[subTableView].rows.length, row);
        });
        // 明细行数
        this.formData[subTableView].total = this.formData[subTableView].rows.length;
      }
    },
    // 明细背景颜色设置
    detailRowStyle (row, rowIndex, detail) {
      var style = "";
      var idVal = row[detail.options.idField];
      if (!idVal) {
        style = "background-color:#ffffdf";
      }
      return style;
    },
    // 明细求和方式
    getDetailSummaries (columns, data, detail) {
      const sums = [];
      // 求和字段
      var sumColumnNames = detail.fields
        .filter(item => {
          return item.isSum;
        })
        .map(item => {
          return item.prop;
        });

      sums[0] = "";
      sums[1] = "";
      detail.fields
        .filter(f => !f.hidden)
        .forEach((field, index) => {
          var footerRows = this.formData[detail.subTableView].footer;
          if (sumColumnNames.indexOf(field.prop) >= 0 && footerRows && footerRows.length) {
            var footerRow = footerRows[0];
            sums[index + 2] = footerRow[field.prop];
          } else {
            sums[index + 2] = "";
          }
        });

      return sums;
    },

    // 字段change事件
    onChange (ref, val, field, formData) {
      this.$emit("on-change", ref, val, field, formData);
    },
    // 字段Focus事件
    onFocus (ref, val, event, field) {
      this.$emit("on-focus", ref, val, event, field);
    },
    // 字段blur事件
    onBlur (ref, val, event, field) {
      this.$emit("on-blur", ref, val, event, field);
    },
    // 明细字段change事件
    onDetailChange (ref, val, row, field, rows) {
      this.$set(row, "__ischange__", true);
      this.$emit("on-detail-change", ref, val, row, field);
      // 自定义事件
      if (field.calcType === "change" && field.calcExpress) {
        // 自定义表达式
        try {
          // eslint-disable-next-line
          eval(field.calcExpress);
        } catch (error) {
          this.$alert(`错误提示：${error}，表达式内容：${field.calcExpress}`, "表达式错误", {
            confirmButtonText: "确定",
            callback: action => {}
          });
        }
      }
      // 计算求和
      if (field.calcMainField) {
        // 主表求和字段计算
        const total = rows.reduce(
          (totalItem, currItem) => {
            totalItem.num += Number(currItem[field.prop]) || 0;
            return totalItem;
          },
          { num: 0 }
        );
        this.$set(this.formData, field.calcMainField, total.num);
      }
      // 关联触发字段
      if (field.calcEmitFields) {
        const emitFields = field.calcEmitFields.split(",");
        for (const emitField of emitFields) {
          const _val = field[emitField];
          const _field = this.getDetailFieldInfo(emitField);
          if (_field) {
            this.onDetailChange(ref, _val, row, _field, rows);
          }
        }
      }
    },
    // 选择items
    handleSelectionChange (val, detail) {
      detail.options.detailSelections = val;
    },
    // 分页大小改变
    handleSizeChange (val, detail) {
      detail.options.pageSize = val;
      this.editData(this.dataOptions.idValue);
    },
    // 当前页码大小改变
    handleCurrentChange (val, detail) {
      detail.options.pageIndex = val;
      this.editData(this.dataOptions.idValue);
    },
    // 通用开启
    open () {
      this.$confirm("确定要进行开启操作吗, 是否继续?", "开启操作", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })

        .then(() => {
          _open();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消开启"
          });
        });

      const _open = () => {
        var idField = this.dataOptions.idField;
        var idValue = this.formData[this.dataOptions.idField];
        var tableName = this.dataOptions.tableView;
        var folder = this.dataOptions.folder;
        var url = "/api/common/open";
        this.initLoading = true;
        var params = {
          idField: idField,
          idValues: [idValue],
          tableName: tableName,
          modelName: tableName,
          folder: folder
        };
        this.common.ajax(
          url,
          params,
          res => {
            this.common.showMsg(res);
            if (res.result) {
              var ref = this.findRef(this.dataListRef);
              ref.loadData();
              this.reload();
              // this.isShowDialog = false;
            }
            this.initLoading = false;
          },
          true
        );
      };
    },
    // 通用终止
    stop () {
      // 终止前事件
      const reValue = this.onStopBefore([this.formData]);
      if (reValue === false) return;

      this.$confirm("确定要进行终止操作吗, 是否继续?", "终止操作", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          _stop();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消终止"
          });
        });

      const _stop = () => {
        var idField = this.dataOptions.idField;
        var idValue = this.formData[this.dataOptions.idField];
        var tableName = this.dataOptions.tableView;
        var folder = this.dataOptions.folder;
        var url = "/api/common/stop";
        this.initLoading = true;
        var params = {
          idField: idField,
          idValues: [idValue],
          tableName: tableName,
          modelName: tableName,
          folder: folder
        };
        this.common.ajax(
          url,
          params,
          res => {
            this.common.showMsg(res);
            if (res.result) {
              var ref = this.findRef(this.dataListRef);
              ref.loadData();
              this.reload();
              // this.isShowDialog = false;
            }
            this.initLoading = false;
          },
          true
        );
      };
    },
    // 通用审核
    auditing () {
      if (this.formData.auditing === 2) {
        this.$message.error("已审核的单子不允许重复审核");
        return;
      }
      this.$confirm("审核后将无法进行修改, 是否继续?", "审核操作", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          _auditing();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "取消审核"
          });
        });

      const _auditing = () => {
        var DBServer = "Sys";
        var url = "/api/common/batchAuditing";
        this.initLoading = true;
        var idValue = this.formData[this.dataOptions.idField];
        var params = Object.assign({}, this.dataOptions, {
          DBServer: DBServer,
          idValues: [idValue],
          auditing: 2
        });
        this.common.ajax(
          url,
          params,
          res => {
            this.common.showMsg(res);
            if (res.result) {
              var ref = this.findRef(this.dataListRef);
              ref.loadData();
              this.isShowDialog = false;
            }
            this.initLoading = false;
          },
          true
        );
      };
    },
    // 复制
    copy () {
      this.$confirm("确定要复制此单据吗?", "复制操作", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => {
          _copy();
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "取消复制"
          });
        });

      const _copy = () => {
        var idField = this.dataOptions.idField;
        var idValue = this.formData[this.dataOptions.idField];
        var where = {};
        where[idField] = idValue;
        var url = "/api/common/copy";
        this.initLoading = true;
        // 明细表
        const detailTableList = this.detailFields.map(item => {
          const opts = item.options;
          opts.subTableView = item.subTableView;
          return opts;
        });
        var params = Object.assign({}, this.dataOptions, {
          idValue: idValue,
          where: where,
          detailTableList: detailTableList
        });

        this.common.ajax(
          url,
          params,
          res => {
            this.common.showMsg(res);
            if (res.result) {
              var ref = this.findRef(this.dataListRef);
              ref.loadData();
              this.$emit("on-copy-after", idValue);
              this.config.visible = false;
            }
            this.initLoading = false;
          },
          true
        );
      };
    },
    // 编辑窗体关闭前事件
    onBeforeClose (done) {
      // 将明细分页码初始化为1
      this.detailFields.forEach(item => {
        item.options.pageIndex = 1;
      });
      const reVal = this.beforeClose();
      if (reVal) {
        done();
      }
    },
    // 批量导入对话框
    importDialog (btnOpts) {
      this.batchImport.visible = true;
      this.batchImport.label = btnOpts.label;
      this.batchImport.options = btnOpts.options;
      this.batchImport.options.fId = this.dataOptions.idValue; // 外键ID
    },
    // 批量导出对话框
    exportDialog (btnOpts) {
      this.batchExport.visible = true;
      this.batchExport.label = btnOpts.label;
      this.batchExport.options = btnOpts.options;
      // 初始化模板
      this.$nextTick(() => {
        this.$refs["export-dialog"].getTemplateList();
      });
    },
    // 批量导入
    importData (exportInfo_Id, vueData_Id) {
      // 刷新数据
      this.editData(this.dataOptions.idValue);
    },
    // 批量导出
    exportData (exportInfo_Id, vueData_Id) {
      var where = this.dataOptions.idField + "=" + this.dataOptions.idValue;
      var url = "/api/common/ExportDataVue";
      var detailInfo = this.detailFields[0];
      var tableName = detailInfo.subTableView;
      var masterTableName = this.dataOptions.tableName || this.dataOptions.tableView;

      var params = {
        projectName: this.dataOptions.projectName,
        masterTableName: masterTableName,
        masterIdField: this.dataOptions.idField,
        tableName: tableName,
        tableView: tableName,
        idField: detailInfo.options.idField,
        where: where,
        sortName: detailInfo.options.idField,
        exportInfo_Id: exportInfo_Id,
        vueData_Id: vueData_Id,
        isDetail: true // 标注为表名导出
      };
      this.initLoading = true;
      var callback = res => {
        this.common.showMsg(res);
        if (res.result) {
          window.open(this.common.domain + res.data);
        }
        this.initLoading = false;
      };
      this.common.ajax(url, params, callback, true);
    },
    // 明细单元格单击事件
    onDetailCellClick (detail, row, col, cell, event) {
      this.$set(detail, "currentRow", row);
      this.$emit("on-detail-cell-click", detail, row, col, cell, event);
    },
    // 明细当前行改变
    onDetailCurrentChange (detail, currentRow, oldCurrentRow) {
      detail.fields.forEach(field => {
        if (field.type === "select" && field.multiple && oldCurrentRow) {
          const v = oldCurrentRow[field.prop];
          if (Array.isArray(v)) {
            oldCurrentRow[field.prop] = v.join("/");
          } else {
            oldCurrentRow[field.prop] = v;
          }
        }
      });
      this.$set(detail, "currentRow", currentRow);
    },
    // 按键抬起
    onKeyup (ref, val, event, field, tableData) {
      this.$emit("on-key-up", ref, val, event, field, tableData);
    },
    // // 行单击
    // onRowClick(row) {
    //   this.$emit("row-click", row);
    // },
    // 按键抬起
    onKeyDown (ref, val, event, field, tableData) {
      this.$emit("on-key-down", ref, val, event, field, tableData);
    },
    // 获得焦点
    onRowChange (ref, selectedRow, field, val) {
      this.$emit("on-row-change", ref, selectedRow, field, val);
    },
    // 获得tableSelect行单击事件
    onRowClick (ref, selectedRow, field) {
      this.$emit("on-row-click", ref, selectedRow, field);
    },
    // 下拉框项单击事件
    onItemClick (ref, val, itemData, field, formData) {
      Object.keys(itemData).forEach(key => {
        this.$set(formData, key, itemData[key]);
      });
      this.$emit("on-item-click", ref, val, itemData, field, formData);
    },
    // 下拉框项单击事件
    editorContainerClick () {
      this.detailFields.forEach(detail => {
        this.$set(detail, "currentRow", null);
        const refs = this.$refs["detail-table-" + detail.subTableView];
        if (refs && refs.length) {
          refs[0].setCurrentRow(null);
        }
      });
    },
    // 明细标题点击事件
    detailHeaderClick (column, event, detail) {
      if (event.target.innerText === "#") {
        this.tableAttr.showAttrDialog = true;
        this.tableAttr.dataOptions = {
          tableView: detail.subTableView,
          idField: detail.options.idField,
          router: this.dataOptions.router,
          menu_Id: this.dataOptions.menu_Id,
          linkColumn: null,
          sortName: detail.options.orderBy
        };
        this.tableAttr.fields = detail.fields.map(item => {
          if (!item.width) {
            item.width = "auto";
          }
          return item;
        });
      }
    },
    // 窗口打开时
    opened () {
      if (Array.isArray(this.$refs.editorInput)) {
        this.$refs.editorInput.forEach(input => {
          input.init();
        });
      }
    },
    // 获得分组fields
    getGroupFields (tabGroupName) {
      const fields = this.masterFields.filter(item => {
        if (tabGroupName === "[未分组]") {
          return !item.tabGroupName;
        } else {
          return item.tabGroupName === tabGroupName;
        }
      });

      return fields;
    },
    // 设置扩展字段数据值
    setExtendFields () {
      // 获得扩展字段
      var getExpandField = (expandFields, fields, dataInfo) => {
        fields.forEach(item => {
          if (item.type === "grid") {
            item.columns.forEach(colItem => {
              getExpandField(expandFields, colItem.fields, dataInfo);
            });
          } else if (item.type === "inline-group") {
            getExpandField(expandFields, item.fields, dataInfo);
            // } else if (item.type === "detail-grid") {
            //   getExpandField(item.fields);
          } else {
            if (item.options && item.options.isExpandField) {
              // 表格对字段时，需要将关联的多字段作为扩展字段
              if (item.options.searchFields) {
                const searchFields = item.options.searchFields.split(",");
                for (let field of searchFields) {
                  if (field.indexOf("as") > 0) {
                    const _fields = field.split("as");
                    field = _fields[1].replace(/ /gi, "");
                    expandFields[field] = dataInfo[field];
                  } else {
                    expandFields[field] = dataInfo[field];
                  }
                }
              } else {
                let v = dataInfo[item.options.prop];
                if (v && ["date", "datetime"].indexOf(item.options.dataType) >= 0) {
                  v = this.common.formatDate(v, item.formatter || "YYYY-MM-DD HH:mm:ss");
                }
                expandFields[item.options.prop] = v;
                if (item.options.keyProp) {
                  const kv = dataInfo[item.options.keyProp];
                  expandFields[item.options.keyProp] = kv;
                }
              }
            } else if (item.isExpandField) {
              // 明细字段
              let v = dataInfo[item.prop];
              if (v && ["date", "datetime"].indexOf(item.dataType) >= 0) {
                v = this.common.formatDate(v, item.formatter || "YYYY-MM-DD HH:mm:ss");
              }
              expandFields[item.prop] = v;
            }
          }
        });
      };

      // 主表字段
      var expandFields = JSON.parse(this.formData.expandFields || "{}");
      getExpandField(expandFields, this.fields, this.formData);
      if (!this.common.isEmptyObject(expandFields)) {
        this.formData.expandFields = JSON.stringify(expandFields);
      } else {
        this.formData.expandFields = null;
      }

      // 明细表字段
      if (this.detailFields.length) {
        for (const detailInfo of this.detailFields) {
          const detailRows = this.getDetailDataList(detailInfo);
          for (const row of detailRows) {
            const expandFields = {};
            getExpandField(expandFields, detailInfo.fields, row);
            if (!this.common.isEmptyObject(expandFields)) {
              row.expandFields = JSON.stringify(expandFields);
            } else {
              row.expandFields = null;
            }
          }
        }
      }
    },
    // 表单验证
    validate () {
      if (this.$refs["editor-form"]) {
        this.$refs["editor-form"].validate();
      }
    },
    // 树形下拉框获得点击项
    onTreeNodeClick (data, node, el, labels, values, field) {
      var the = this;
      // 仅选择叶节点
      if (!node.isLeaf && field.options.onlySelectLeaf) return;

      var key = field.options.prop;
      // 将下拉框中的值赋给表单
      if (Object.keys(data).findIndex(item => item === key) >= 0) {
        Object.keys(data).forEach((key, index) => {
          if (["value", "label", "hasChild", "hasFactChild", "state", "attributes"].indexOf(key) < 0) {
            the.$set(the.formData, key, data[key]);
          }
        });
      } else {
        the.$set(the.formData, key, data[key]);
      }
      this.$emit("on-tree-node-click", data, node, el, labels, values, field);
    },
    // 排序
    sortChange ({ column, prop, order }) {
      const fields = this.detailFields[0].fields;
      const options = this.detailFields[0].options;
      options.orderBy = {};
      order = order === "ascending" ? "ASC" : "DESC";
      // 扩展字段
      const colInfo = fields.find(item => item.prop === prop);
      if (colInfo.isExpandField) {
        options.orderBy = {
          prop: prop,
          order: order,
          isExpandField: true
        };
      } else {
        options.orderBy[prop] = order;
        delete options.orderBy.order;
        delete options.orderBy.isExpandField;
      }
      this.reload();
    },
    // 文件上传完毕后事件
    onUploadAfter (ref, file, field, formData) {
      this.$emit("on-upload-after", ref, file, field, formData);
    },
    /**
     * 主表字段控制是否可编辑
     * 当disabled=true时，excludeFields集合中的排除字段可以编辑，其他字段不可编辑
     * 当disabled=false时，excludeFields集合中的排除字段不可以编辑，其他字段可编辑
     * @excludeField 排除字段
     */
    setFieldsDisabled (excludeFields, disabled) {
      // 获得扩展字段
      const getFieldInfo = fields => {
        fields.forEach(item => {
          if (item.type === "grid") {
            item.columns.forEach(colItem => {
              getFieldInfo(colItem.fields);
            });
          } else if (item.type === "inline-group") {
            getFieldInfo(item.fields);
          } else {
            if (item.options) {
              if (disabled) {
                if (excludeFields.indexOf(item.options.prop) >= 0) {
                  this.$set(item.options, "disabled", false);
                  // this.$set(item.options, "readonly", false);
                } else {
                  this.$set(item.options, "disabled", true);
                  // this.$set(item.options, "readonly", true);
                }
              } else {
                if (excludeFields.indexOf(item.options.prop) >= 0) {
                  this.$set(item.options, "disabled", true);
                  // this.$set(item.options, "readonly", true);
                } else {
                  this.$set(item.options, "disabled", false);
                  // this.$set(item.options, "readonly", false);
                }
              }
            }
          }
        });
      };

      // 主表字段
      getFieldInfo(this.fields);
    },
    /**
     * 明细字段控制是否可编辑
     * 当disabled=true时，excludeFields集合中的排除字段可以编辑，其他字段不可编辑
     * 当disabled=false时，excludeFields集合中的排除字段不可以编辑，其他字段可编辑
     * @excludeField 排除字段
     */
    setDetailFieldsDisabled (detailFields, excludeFields, disabled) {
      if (!Array.isArray(detailFields)) return;

      detailFields.forEach(colItem => {
        if (disabled) {
          if (excludeFields.indexOf(colItem.prop) >= 0) {
            colItem.readonly = false;
          } else {
            colItem.readonly = true;
          }
        } else {
          if (excludeFields.indexOf(colItem.prop) >= 0) {
            colItem.readonly = true;
          } else {
            colItem.readonly = false;
          }
        }
      });
    },
    // 改变当前数据上一条，下一条
    onChangeItem (type) {
      var ref = this.findRef(this.dataListRef);
      if (!ref) return;
      const idValue = this.formData[this.dataOptions.idField];
      let newItem = {};
      const currentIndex = ref.dataList.findIndex(item => item[this.dataOptions.idField] === idValue);
      if (type === "prev") {
        newItem = ref.dataList[currentIndex - 1];
      } else if (type === "next") {
        newItem = ref.dataList[currentIndex + 1];
      }
      if (newItem) {
        const idValue = newItem[this.dataOptions.idField];
        this.editData(idValue);
      } else {
        this.$message.info("没有获取到数据");
      }
    },
    // 明细展开事件
    onExpandChange (row, expandedRows, detail, index) {
      this.$emit("on-expand-change", row, expandedRows, detail, index);
    }
  }
};
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.editor-container {
  padding-bottom: 10px;
  .splitter-title {
    background-color: #f2f6fc;
    padding: 0px 10px;
    margin-bottom: 10px;
    border-bottom: #dcdfe6 2px double;
    position: relative;
    .title {
      padding: 5px 3px;
      border-bottom: #036fba 3px solid;
      font-size: 16px;
      display: inline-block;
      position: relative;
      bottom: -2px;
    }
  }

  .editor-detail {
    .detail-tool {
      margin-bottom: 0px;
      padding: 10px 0;
      .el-button--mini {
        padding: 7px 7px;
      }
      .tool-group + .tool-group {
        margin-left: 10px;
      }
      .el-button--medium {
        padding: 10px 10px;
      }
    }
    + .editor-detail {
      margin-top: 20px;
    }
    .button-box {
      float: right;

      .detail-btn {
        padding: 7px 7px;
      }
    }
  }
  .editor-detail-border {
    border-top: 1px solid #ebeef5;
    position: relative;
  }

  ::v-deep .el-input__inner {
    padding: 0 5px;
  }

  ::v-deep .el-input-number.is-controls-right .el-input__inner {
    padding-left: 5px;
    padding-right: 40px;
  }

  ::v-deep .el-input--prefix .el-input__inner {
    padding: 0 5px 0 25px;
  }
  ::v-deep td {
    padding: 3px 0;
  }

  ::v-deep .col-container {
    .el-input--suffix .el-input__inner {
      padding: 0 5px;
    }
    ::v-deep .el-input--prefix .el-input__inner {
      padding: 0 5px 0 25px;
    }
    .cell {
      padding-left: 5px;
      padding-right: 5px;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    .el-input-number.is-controls-right .el-input__inner {
      padding-left: 5px;
      padding-right: 30px;
    }
  }

  ::v-deep .el-input__prefix {
    left: 0;
  }

  ::v-deep .el-input__suffix {
    right: 0;
  }
  ::v-deep .el-checkbox + .el-checkbox,
  ::v-deep .el-radio + .el-radio {
    margin-left: 0px !important;
  }
}

.dialog-footer {
  ::v-deep .el-button {
    padding: 10px 10px !important;
  }
}
</style>

<style rel="stylesheet/scss" lang="scss">
.editor-dialog {
  .el-dialog__body {
    padding: 10px 20px 10px 10px;
  }
  .pagination-container {
    margin-top: 10px;
  }
}
</style>
